/**
 * LifeService框架工具函数
 */

// 深度合并对象
export function deepMerge(target, source) {
  if (!isObject(target) || !isObject(source)) {
    return source;
  }

  for (const key in source) {
    if (isObject(source[key])) {
      if (!target[key]) {
        Object.assign(target, { [key]: {} });
      }
      deepMerge(target[key], source[key]);
    } else {
      Object.assign(target, { [key]: source[key] });
    }
  }
  
  return target;
}

// 检查值是否为对象
export function isObject(value) {
  return value && typeof value === 'object' && !Array.isArray(value);
}

// 检查值是否为函数
export function isFunction(value) {
  return typeof value === 'function';
}

// 创建单例工厂函数
export function createSingleton(Constructor) {
  let instance;
  return (...args) => {
    if (!instance) {
      instance = new Constructor(...args);
    }
    return instance;
  };
}

// 延迟执行函数
export function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

// 重试函数
export async function retry(fn, options = {}) {
  const {
    retries = 3,
    delay: ms = 1000,
    onRetry = () => {}
  } = options;

  for (let i = 0; i < retries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (i === retries - 1) throw error;
      await onRetry(i, error);
      await delay(ms * Math.pow(2, i)); // 指数退避
    }
  }
}

// 错误处理包装器
export function withErrorHandling(fn, fallback = null, errorHandler = null) {
  return async function(...args) {
    try {
      return await fn.apply(this, args);
    } catch (error) {
      if (errorHandler) {
        errorHandler(error, args);
      }
      return fallback;
    }
  };
}

// 防抖函数
export function debounce(func, wait, immediate = false) {
  let timeout;
  return function executedFunction(...args) {
    const later = () => {
      timeout = null;
      if (!immediate) func.apply(this, args);
    };
    const callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(this, args);
  };
}

// 节流函数
export function throttle(func, limit) {
  let inThrottle;
  return function(...args) {
    if (!inThrottle) {
      func.apply(this, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}